package insight.Expression;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
 * @author huu
 * @create 2025-08-24-12:25
 * @description: 将中缀表达式转为后缀表达式后再运算
 */
public class transform {
    private String infix;
    public transform(String infix)
    {
        this.infix = infix;
    }
    public List<String> toPostfix() {
        int index = 0;
        //辅助栈
        LinkedList<String> stack = new LinkedList<>();
        //结果集
        List<String> result = new ArrayList<>();
        while (index < infix.length()) {
            //1.遇见操作数直接push结果集
            //2.遇到左括号，入辅助栈
            //3.遇到右括号，将辅助栈中的元素pop到结果集，直到遇到左括号为止
            //4.运算符，将辅助栈中的元素pop到结果集，直到遇到运算符的优先级小于当前运算符的优先级为止
            char c = infix.charAt(index);
            if(c == '('){
                stack.addLast("(");
            }else if(c == ')'){
                //bug日志---------------------这里的stack.getLast()方法和stack.peek()方法不一样
                //使用peek()会出现左括号不匹配也就是下面运行时异常问题
                /*在 LinkedList 中：
                    peek() - 返回第一个元素（头部）
                    getLast() - 返回最后一个元素（尾部*/
                while(!stack.isEmpty() && !stack.getLast().equals("(")){
                    result.add(stack.removeLast());
                }
                // 弹出左括号前检查栈是否为空
                if (!stack.isEmpty()) {
                    stack.removeLast(); // 弹出左括号
                } else {
                    throw new RuntimeException("括号不匹配：缺少左括号");
                }
            }else if(c == '*' || c =='/'){
                while (!stack.isEmpty() && (stack.getLast().equals("*") || stack.getLast().equals("/"))) {
                    result.add(stack.removeLast());
                }
                //c+""----> char 转 string
                //入栈
                stack.addLast(c + "");
            }else if(c == '+' || c == '-'){
                while (isOperator(stack)) {
                    result.add(stack.removeLast());
                }
                //入栈
                stack.addLast(c + "");
            }else if(Character.isDigit(c)){
                //数字可能多个字符，需要存储
                StringBuilder number = new StringBuilder();
                while (index < infix.length() && Character.isDigit(infix.charAt(index))) {
                    number.append(infix.charAt(index));
                    index++;
                }
                index--;
                result.add(number.toString());
            }else{
                throw new RuntimeException("无效字符");
            }
            index++;
        }
        while (!stack.isEmpty()) {
            result.add(stack.removeLast());
        }
        return result;
    }
    public boolean isOperator(LinkedList<String> stack){
        if(stack.isEmpty()){
            return false;
        }
        return Set.of("+","-","*","/").contains(stack.getLast());
        //return c.equals("*") || c.equals("/") || c.equals("+") || c.equals("-");
        //或者可以创建一个set使用set.contains(c)
    }

    //返回真正的表达式
    public Expression parse(){
        List<String> suffix = this.toPostfix();
        LinkedList<Expression> stack = new LinkedList<>();
        for(String item : suffix){
            if(item.equals("+")){
                Expression right = stack.removeLast();
                stack.addLast(new AddExpression(stack.removeLast(), right));
            }else if(item.equals("-")){
                Expression right = stack.removeLast();
                stack.addLast(new SubExpression(stack.removeLast(), right));
            }else if(item.equals("*")){
                Expression right = stack.removeLast();
                stack.addLast(new MultiplyExpression(stack.removeLast(), right));
            }else if(item.equals("/")){
                Expression right = stack.removeLast();
                stack.addLast(new DevisionExpression(stack.removeLast(), right));
            }else{
                stack.addLast(new NumberExpression(Integer.parseInt(item)));
            }
        }
        return stack.removeLast();
    }

}
